home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / zm16src.lzh / EXPANDAR.C < prev    next >
C/C++ Source or Header  |  1988-05-19  |  15KB  |  701 lines

  1.  
  2.     /* 
  3.      *     Examine each argument given to expandargs()
  4.      *     If it is a directory, then expand it
  5.      *    to all its component files, recursively
  6.      *    till you bottom out.
  7.      *    If it is not a directory, then just pass it on.
  8.      *
  9.      *    Inputs: routine, argc, argv
  10.      *    Outputs: nargc, nargv (calls routine(nargc, nargv))
  11.      *    To test: compile with -DTEST
  12.      *         define MWC if using Mark Williams C
  13.      *         run with a directory as an arg
  14.      *    Author: JRB    bammi@mandrill.ces.CWRU.edu
  15.      *    Requirements: Mark Williams C or Alcyon C
  16.      *        Wants lots of Dynamic memory. It
  17.      *        all depends upon how many files you
  18.      *        have. Use the -P option to prune
  19.      *        out subdirectories and do things
  20.      *        one at a time, if you keep running
  21.      *        out of memory.
  22.      *        With Mark Williams i use _stksize = 128K
  23.      *        With Alcyon i use memory model 2 (half of
  24.      *        of avail memory) in GEMSTART.S
  25.      *
  26.          *      WARNINGS: Be CAREFUL about the 40 folder bug. Use
  27.      *              GEMBOOT or FOLDRXXX when dealing with
  28.      *          a deeply nested file structure.
  29.      *
  30.      *    Added -P name prune option at the suggestion of dietz@zhmti
  31.      *    Multiple -P's may be given on the command line.
  32.      *    -P name may be given anywhere on the command line. -P name
  33.      *    will prune the subdirectories named as arguement to -P.
  34.      *    ie: when the program is decending the file hierarchy it
  35.      *    will not visit the pruned branches.
  36.      *     NOTE that the option is -P and not -p
  37.      *          (-p is a valid sz option).
  38.      *    NOTE that the arguement given to -P can be the name
  39.      *     of a file or a directory. In case it is a file,
  40.      *    that file is skipped.
  41.      *
  42.      */
  43.  
  44. /*
  45.  * Expand argc, so that the called routine(nargc,nargv) receives only
  46.  * filenames, in nargv[][]
  47.  *
  48.  ************************************************************************
  49.  *                                    *
  50.  *      WARNING:  Be CAREFUL about the 40 folder bug. Use        *
  51.  *              GEMBOOT or FOLDRXXX when dealing with            *
  52.  *          a deeply nested file structure.            *
  53.  *                                    *
  54.  ************************************************************************
  55.  *
  56.  *    Jwahar R. Bammi
  57.  *            usenet: mandrill!bammi@{decvax,sun}.UUCP
  58.  *            csnet:  bammi@mandrill.ces.CWRU.edu
  59.  *            arpa:   bammi@mandrill.ces.CWRU.edu
  60.  *            CompuServe: 71515,155
  61.  *
  62.  */
  63.  
  64. #ifdef TEST
  65. #include <stdio.h>
  66. #include <osbind.h>
  67. #include <ctype.h>
  68. #endif
  69.  
  70. #ifdef TRUE
  71. #undef TRUE
  72. #endif
  73. #ifdef OK
  74. #undef OK
  75. #endif
  76. #ifdef FALSE
  77. #undef FALSE
  78. #endif
  79.  
  80. #define TRUE     1
  81. #define OK     0
  82. #define FALSE     0
  83. #define Realloc     realloc
  84.  
  85. #ifdef TEST
  86. struct    stat
  87. {
  88.     char    st_sp1[21];    /* Junk        */
  89.     char    st_mode;       /* File attributes */
  90.     int    st_time;       /* Mod Time      */
  91.     int     st_date;       /* Mod date      */
  92.     long    st_size;       /* File size       */
  93.     char    st_name[14];   /* File name       */
  94. };
  95. #endif
  96.  
  97. typedef struct _prunelist {
  98.     char *name;            /* name of subdirectory to prune */
  99.     struct _prunelist *next;    /* ptr to next */
  100. } PRUNELIST;
  101.  
  102. static char *ProgName;
  103. static PRUNELIST *PruneList = (PRUNELIST *)NULL; /* Head of PruneList */
  104.  
  105. static char **CopyToNargv();
  106. static char **ExpandStack();
  107. static void FreeStack();
  108. static void FreeNargv();
  109. static void FreePrune();
  110. static void FreeUp();
  111. static int PushDir();
  112. static char *PopDir();
  113. static int ProcessDirs();
  114. static PRUNELIST *AddPrune();
  115. static int OnPruneList();
  116. static int isdir();
  117.  
  118. extern int existd();
  119.  
  120. expandargs(routine, argc, argv)
  121. int (*routine)();
  122. int argc;
  123. char **argv;
  124. {
  125.     register int status;
  126.     int nargc;
  127.     char **nargv;
  128.     extern char **CopyToNargv();
  129.     extern PRUNELIST *AddPrune();
  130.     extern int existd();
  131.  
  132.     nargc = 0;
  133.     nargv = (char **)NULL;
  134.     ProgName = *argv;
  135.     
  136.     /* copy argv[0] blindly */
  137.     if((nargv = CopyToNargv(*argv, nargc, nargv)) == (char **)NULL)
  138.     {
  139.         FreeUp(nargc, nargv);
  140.         return(~OK);
  141.     }
  142.  
  143.     nargc++;
  144.     
  145.     while((--argc) > 0)
  146.     {
  147.         argv++;
  148.         if(**argv == '-')
  149.         {
  150.             /* copy any options except -P */
  151. #ifdef TEST
  152.             /* some shell pass -P as -p */
  153.             if( ((*argv)[1] == 'P') || ((*argv)[1] == 'p'))
  154. #else
  155.             if( (*argv)[1] == 'P')
  156. #endif
  157.             {
  158.                 if((--argc) <= 0)
  159.                 {
  160.                     fprintf(STDERR,"no argument given to -P\n");
  161.                     FreeUp(nargc, nargv);
  162.                     return(~OK);
  163.                 }
  164.                 if((PruneList = AddPrune(PruneList,*++argv))
  165.                    == (PRUNELIST *)NULL)
  166.                 {
  167.                     FreeUp(nargc, nargv);
  168.                     return(~OK);
  169.                 }
  170.             }
  171.             else
  172.             {
  173.                 if((nargv = CopyToNargv(*argv, nargc, nargv))
  174.                    == (char **)NULL)
  175.                 {
  176.                     FreeUp(nargc, nargv);
  177.                     return(~OK);
  178.                 }
  179.                 else
  180.                     nargc++;
  181.             }
  182.             
  183.         }
  184.         else
  185.         {
  186.             /* If its not on the PruneList then */
  187.             if(!OnPruneList(PruneList, *argv))
  188.             {
  189.                 /* if it is a directory, push it */
  190.                 if(existd(*argv))
  191.                 {
  192.                     if((status = PushDir(*argv)) != OK)
  193.                     {
  194.                         FreeUp(nargc, nargv);
  195.                         return(status);
  196.                     }
  197.                 }
  198.                 else
  199.                 {
  200.                     /* it is NOT a directory, copy to nargv */
  201.                     if((nargv = CopyToNargv(*argv, nargc, nargv))
  202.                        == (char **)NULL)
  203.                     {
  204.                         FreeUp(nargc, nargv);
  205.                         return(~OK);
  206.                     }
  207.                     else
  208.                         nargc++;
  209.                 }
  210.             }
  211.         }
  212.     } /* while */
  213.  
  214.     /* process pushed directories if any */
  215.     if((status = ProcessDirs(&nargc, &nargv)) != OK)
  216.     {
  217.         FreeUp(nargc, nargv);
  218.         return(status);
  219.     }
  220.     /* else Free the Stack and Prune List, call *routine */
  221.     FreeStack();
  222.     FreePrune();
  223.     status =  (*routine)(nargc, nargv);
  224.     FreeNargv(nargc, nargv);
  225.  
  226.     return status;
  227.  
  228. }
  229.  
  230. /*
  231.  * Expand nargv by an element and copy a String into the new element
  232.  *
  233.  */
  234. static char **CopyToNargv(string, nargc, nargv)
  235. char *string;
  236. int nargc;
  237. char **nargv;
  238. {
  239.     extern char *malloc(), *Realloc(), *strcpy();
  240.     extern int strlen();
  241.     
  242.     /* expand nargv by 1 element */
  243.     if(nargv == (char **)NULL)
  244.         /* do it with malloc for the first one */
  245.         nargv = (char **)malloc(sizeof(char **));
  246.     else
  247.         /* do it with Realloc for others */
  248.         nargv = (char **)Realloc(nargv, (nargc+1)*sizeof(char **));
  249.     
  250.     if(nargv == (char **)NULL)
  251.     {
  252.         /* failed to get memory */
  253.         fprintf(STDERR,"%s(CopyToNargv()): Out of Memory\n", ProgName);
  254.         return ((char **)NULL);
  255.     }
  256.  
  257.     /* Get mem for string */
  258.     if(( nargv[nargc] = malloc(strlen(string)+1)) == (char *)NULL)
  259.     {
  260.         /* failed to get memory */
  261.         fprintf(STDERR,"%s(CopyToNargv()): Out of Memory\n", ProgName);
  262.         return ((char **)NULL);
  263.     }
  264.  
  265.     /* copy string into nargv[nargc] */
  266.     (void)strcpy( nargv[nargc], string);
  267.     return(nargv);
  268. }
  269.  
  270. static char **Stack = (char **)NULL;    /* directory stack */
  271. static char StackSize = 0;        /* Size of current Stack */
  272. static int    Top   = -1;
  273. #define STACK_EMPTY    (Top < 0)
  274. #define CHUNKSIZE    16
  275.  
  276. /*
  277.  * Grow the Stack by one chunk of CHUNKSIZE elements
  278.  *
  279.  */
  280. static char **ExpandStack(Stack)
  281. char **Stack;
  282. {
  283.     extern char *malloc(), *Realloc();
  284.     
  285.     /* Grow Stack */
  286.     if(Stack == (char **)NULL)
  287.         /* with malloc */
  288.         Stack = (char **)malloc(CHUNKSIZE * sizeof(char **));
  289.     else
  290.         /* with Realloc */
  291.         Stack = (char **)Realloc(Stack, (StackSize+CHUNKSIZE) *
  292.                              sizeof(char **));
  293.  
  294.     if(Stack == (char **)NULL)
  295.     {
  296.         /* outa mem */
  297.         fprintf(STDERR,"%s(ExpandStack()): Out of Memory\n", ProgName);
  298.         return((char **)NULL);
  299.     }
  300.     StackSize += CHUNKSIZE;
  301.     return(Stack);
  302. }
  303.  
  304. /*
  305.  * Free the Stack
  306.  *
  307.  */
  308. static void FreeStack()
  309. {
  310.     if(StackSize > 0)
  311.         (void)free(Stack);
  312.     Stack = (char **)NULL;
  313.     StackSize = 0;
  314.     Top   = -1;
  315. }
  316.  
  317. /*
  318.  * Free Nargv
  319.  *
  320.  */
  321. static void FreeNargv(nargc, nargv)
  322. int nargc;
  323. char *nargv[];
  324. {
  325.     register int i;
  326.  
  327.     for(i = 0; i < nargc; i++)
  328.         (void)free(nargv[i]);
  329.     if(nargc > 0)
  330.         (void)free(nargv);
  331. }
  332.  
  333. /*
  334.  * Free the PruneList
  335.  *
  336.  */
  337. static void FreePrune()
  338. {
  339.     register PRUNELIST *p, *next;
  340.  
  341.     for(p = PruneList; p != (PRUNELIST *)NULL; p = next)
  342.     {
  343.         next = p->next;
  344.         (void)free(p);
  345.     }
  346.     PruneList = (PRUNELIST *)NULL;
  347. }
  348.  
  349. /*
  350.  * FreeUp before bad exit
  351.  *
  352.  */
  353. static void FreeUp(nargc, nargv)
  354. int nargc;
  355. char **nargv;
  356. {
  357.     FreeStack();
  358.     FreePrune();
  359.     FreeNargv(nargc, nargv);
  360. }
  361.  
  362. /*
  363.  * Push a directory name on Stack
  364.  *
  365.  */
  366. static int PushDir(name)
  367. char *name;
  368. {
  369.